package fwmpc.service.impl;

import fdupc.date.DateUtil;
import fdupc.date.DateUtilConstant;
import fwmpc.interact.IWeiXinInteraction;
import fwmpc.resource.IWeiXinAttributeItem;
import fwmpc.service.bean.WxTemplateMessage;
import fwmpc.store.IWeiXinAttributeStore;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ssl.SSLContexts;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.http.MediaType;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

/**
 * 类描述:  微信-小程序业务处理处理Service
 *
 * @author 王雷
 * @version 1.0.0
 * @date 2021/1/21 0021 下午 10:15
 */
@Slf4j
public abstract class WeiXinAppletsManagerService extends AbstractWeiXinBasicGeneralInformationService {

    /**
     * 功能描述：微信-小程序业务处理处理Service
     *
     * @param iWeiXinInteraction    微信通讯配置对象
     * @param iWeiXinAttributeStore 微信属性存储对象
     * @author : 王雷
     * @date : 2021/1/21 0021 下午 10:19
     */
    public WeiXinAppletsManagerService(IWeiXinInteraction iWeiXinInteraction
            , IWeiXinAttributeStore iWeiXinAttributeStore) {
        super(iWeiXinInteraction, iWeiXinAttributeStore);
    }

    /**
     * 功能描述：微信换取支付链接处理
     *
     * @param appId 标识
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2021/1/21 0021 上午 11:37
     */
    @Override
    public String givePaymentLink(String appId) throws Exception {
        final Map<String, Object> params = new HashMap<>(16);
        params.put("CodeUrl", iWeiXinAttributeStore.giveCodeUrl());
        params.put("AppId", appId);
        params.put("PayCallBackUrl", iWeiXinAttributeStore.givePayCallBackUrlEncodeUrl());
        return new SpelExpressionParser().parseExpression(iWeiXinAttributeStore.givePaymentLink(), new TemplateParserContext())
                .getValue(params, String.class);
    }

    /**
     * 功能描述：统一支付处理
     *
     * @param appId          微信标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @param openId         支付者OpenId
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2021/1/21 0021 上午 11:37
     */
    @Override
    public Map<String, String> unifiedAppletsPaymentProcessing(String appId, BigDecimal totalFee, String bodyValue, String outTradeNo
            , String spbillCreateIp, String openId) throws Exception {
        /*final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        if (StringUtil.IsNullOrBlank(appId)) {
            appId = iWeiXinAttributeItem.giveAppId();
        }
        final IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataByAppIdToMap(appId, totalFee);*/
        Map<String, Object> paraMap = new HashMap<>(16);
        givePayParameter(paraMap, appId, totalFee, bodyValue, outTradeNo, spbillCreateIp, openId, Boolean.FALSE);
        /*{
            private static final long serialVersionUID = 3064416816921328672L;

            {
                put("total_fee", totalFee.multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_HALF_UP).toString());
                put("body", StringUtil.isNotBlank(bodyValue) ? iWeiXinAttributeItem.giveOrderBodyValue() : bodyValue);
                put("mch_id", mchDataBean.getMchId());
                put("MCHSECRET", mchDataBean.getPayMchSecret());
                put("out_trade_no", outTradeNo);
                put("spbill_create_ip", spbillCreateIp);
                put("openid", openId);
                put("nonce_str", createNonceStr());
                put("trade_type", "JSAPI");
                //订单失效时间
                put("time_expire", DateUtil.format(Date.from(LocalDateTime.now().plusSeconds(iWeiXinAttributeItem.givePayWaitingCycle())
                        .atZone(ZoneId.systemDefault()).toInstant()), DateUtil.PATTERN_YYYYMMDDHHMMSS));
            }
        };
        paraMap.put("appid", appId);
        paraMap.put("notify_url", iWeiXinAttributeStore.givePayCallBackUrl(appId));
        paraMap.put("sign", dataSignManager(paraMap, mchDataBean.getPayMchSecret()));*/
        log.error("支付参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveUnifiedOrderUrl(), String.class, requestHeaders -> {
                    requestHeaders.setContentType(MediaType.APPLICATION_XML);
                }
                , () -> mapToXmlWith(paraMap), parameter -> {
                    /*parameter.add("appid", wxaItem.giveAppId());
                    parameter.add("secret", wxaItem.giveAppSecret());
                    parameter.add("js_code", code);
                    parameter.add("grant_type", GRANT_TYPE_VALUE);*/
                }, reqeustValue -> {
                    log.error("统一支付接口处理结果为：{}", reqeustValue);
                    return strToXmlParse(reqeustValue);
                });
    }

    /**
     * 功能描述：统一支付处理
     *
     * @param appId          微信标识
     * @param platformId     平台标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @param openId         支付者OpenId
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2021/1/21 0021 上午 11:37
     */
    @Override
    public Map<String, String> unifiedAppletsPaymentProcessing(String appId, Long platformId, BigDecimal totalFee
            , String bodyValue, String outTradeNo, String spbillCreateIp, String openId) throws Exception {
        Map<String, Object> paraMap = new HashMap<>(16);
        givePayParameter(paraMap, appId, platformId, totalFee, bodyValue, outTradeNo, spbillCreateIp, openId, Boolean.FALSE);
        log.error("支付参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveUnifiedOrderUrl(), String.class, requestHeaders -> {
                    requestHeaders.setContentType(MediaType.APPLICATION_XML);
                }
                , () -> mapToXmlWith(paraMap), parameter -> {
                }, reqeustValue -> {
                    log.error("统一支付接口处理结果为：{}", reqeustValue);
                    return strToXmlParse(reqeustValue);
                });
    }

    /**
     * 功能描述：统一支付处理——H5
     *
     * @param appId          平台标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2021/1/21 0021 上午 11:37
     */
    @Override
    public Map<String, String> unifiedAppletsPaymentProcessingByWeb(String appId, BigDecimal totalFee, String bodyValue, String outTradeNo
            , String spbillCreateIp) throws Exception {
        Map<String, Object> paraMap = new HashMap<>(16);
        givePayParameter(paraMap, appId, totalFee, bodyValue, outTradeNo, spbillCreateIp, null, Boolean.TRUE);
        log.error("支付参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveUnifiedOrderUrl(), String.class, requestHeaders -> {
                    requestHeaders.setContentType(MediaType.APPLICATION_XML);
                }
                , () -> mapToXmlWith(paraMap), parameter -> {
                }, reqeustValue -> {
                    log.error("统一支付接口处理结果为：{}", reqeustValue);
                    return strToXmlParse(reqeustValue);
                });
    }

    /**
     * 功能描述：统一支付处理——H5
     *
     * @param appId          微信标识
     * @param platformId     平台标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2021/1/21 0021 上午 11:37
     */
    @Override
    public Map<String, String> unifiedAppletsPaymentProcessingByWeb(String appId, Long platformId, BigDecimal totalFee, String bodyValue, String outTradeNo
            , String spbillCreateIp) throws Exception {
        Map<String, Object> paraMap = new HashMap<>(16);
        givePayParameter(paraMap, appId, platformId, totalFee, bodyValue, outTradeNo, spbillCreateIp, null, Boolean.TRUE);
        log.error("支付参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveUnifiedOrderUrl(), String.class, requestHeaders -> {
                    requestHeaders.setContentType(MediaType.APPLICATION_XML);
                }
                , () -> mapToXmlWith(paraMap), parameter -> {
                }, reqeustValue -> {
                    log.error("统一支付接口处理结果为：{}", reqeustValue);
                    return strToXmlParse(reqeustValue);
                });
    }

    private static final String PAY_WEB_H5_SCENE_INFO = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://old.sltonline.cn/title\",\"wap_name\":\"商城支付\"}}";

    /**
     * 功能描述：支付参数处理
     *
     * @param parameterMap   参数容器
     * @param appId          平台标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @param openId         支付者OpenId
     * @param isWeb          是否是H5
     * @throws Exception 处理异常
     * @date : 2022/8/4 0004 上午 11:31
     */
    protected void givePayParameter(Map<String, Object> parameterMap, String appId, BigDecimal totalFee, String bodyValue
            , String outTradeNo, String spbillCreateIp, String openId, boolean isWeb) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        if (!StringUtils.isNotEmpty(appId)) {
            appId = iWeiXinAttributeItem.giveAppId();
        }
        final IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataByAppIdToMap(appId, totalFee);
        parameterMap.put("appid", appId);
        parameterMap.put("total_fee", totalFee.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).toString());
        parameterMap.put("body", StringUtil.isNotBlank(bodyValue) ? iWeiXinAttributeItem.giveOrderBodyValue() : bodyValue);
        parameterMap.put("mch_id", mchDataBean.getMchId());
        parameterMap.put("MCHSECRET", mchDataBean.getPayMchSecret());
        parameterMap.put("out_trade_no", outTradeNo);
        parameterMap.put("spbill_create_ip", spbillCreateIp);
        parameterMap.put("nonce_str", createNonceStr());
        parameterMap.put("trade_type", (!isWeb) ? "JSAPI" : "MWEB");
        if (isWeb) {
            parameterMap.put("scene_info", PAY_WEB_H5_SCENE_INFO);
        } else {
            parameterMap.put("openid", openId);
        }
        //订单失效时间
        parameterMap.put("time_expire", DateUtil.format(DateUtil.dateCalculate(iWeiXinAttributeItem.givePayWaitingCycle())
                , DateUtilConstant.PATTERN_YYYYMMDDHHMMSS));

        parameterMap.put("notify_url", iWeiXinAttributeStore.givePayCallBackUrl(appId));
        parameterMap.put("sign", dataSignManager(parameterMap, mchDataBean.getPayMchSecret()));
    }

    /**
     * 功能描述：支付参数处理
     *
     * @param parameterMap   参数容器
     * @param appId          微信标识
     * @param platformId     平台标识
     * @param totalFee       支付金额；
     * @param bodyValue      产品说明
     * @param outTradeNo     订单编号
     * @param spbillCreateIp 发起者IP
     * @param openId         支付者OpenId
     * @param isWeb          是否是H5
     * @throws Exception 处理异常
     * @date : 2022/8/4 0004 上午 11:31
     */
    protected void givePayParameter(Map<String, Object> parameterMap, String appId, Long platformId, BigDecimal totalFee
            , String bodyValue, String outTradeNo, String spbillCreateIp, String openId, boolean isWeb) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        if (StringUtils.isEmpty(appId)) {
            appId = iWeiXinAttributeItem.giveAppId();
        }
        final IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataByAppIdToMap(appId, totalFee);
        parameterMap.put("appid", appId);
        parameterMap.put("total_fee", totalFee.multiply(BigDecimal.valueOf(100))
                .setScale(0, RoundingMode.HALF_UP).toString());
        parameterMap.put("body", StringUtil.isNotBlank(bodyValue) ? iWeiXinAttributeItem.giveOrderBodyValue() : bodyValue);
        parameterMap.put("mch_id", mchDataBean.getMchId());
        parameterMap.put("MCHSECRET", mchDataBean.getPayMchSecret());
        parameterMap.put("out_trade_no", outTradeNo);
        parameterMap.put("spbill_create_ip", spbillCreateIp);
        parameterMap.put("nonce_str", createNonceStr());
        parameterMap.put("trade_type", (!isWeb) ? "JSAPI" : "MWEB");
        if (isWeb) {
            parameterMap.put("scene_info", PAY_WEB_H5_SCENE_INFO);
        } else {
            parameterMap.put("openid", openId);
        }
        //订单失效时间
        parameterMap.put("time_expire", DateUtil.format(DateUtil.dateCalculate(iWeiXinAttributeItem.givePayWaitingCycle())
                , DateUtilConstant.PATTERN_YYYYMMDDHHMMSS));

        parameterMap.put("notify_url", iWeiXinAttributeStore.givePayCallBackUrl(appId));
        parameterMap.put("sign", dataSignManager(parameterMap, mchDataBean.getPayMchSecret()));
    }

//    /**
//     * 功能描述：统一退款处理——小程序
//     *
//     * @param appId         平台标识
//     * @param refundFee     退款金额；
//     * @param totalFee      订单支付总金额；
//     * @param outRefundNo   支付单号；
//     * @param transactionId 微信支付单号
//     * @param sslContext    CA拓展对象；
//     * @throws Exception 处理异常
//     * @author : 王雷
//     * @date : 2022/7/19 0019 上午 11:12
//     */
//    @Override
//    public Map<String, String> unifiedRefundProcessing(String appId, BigDecimal refundFee, BigDecimal totalFee
//            , String outRefundNo, String transactionId, SSLContext sslContext) throws Exception {
//        return unifiedRefundProcessing(appId, refundFee, totalFee, outRefundNo, transactionId, sslContext, null);
//    }

    /**
     * 功能描述：统一退款处理——小程序
     *
     * @param appId         平台标识
     * @param refundFee     退款金额；
     * @param totalFee      订单支付总金额；
     * @param outRefundNo   支付单号；
     * @param transactionId 微信支付单号
     * @param sslContext    CA拓展对象；
     * @param mchId         商户号；
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public Map<String, String> unifiedRefundProcessing(String appId, BigDecimal refundFee, BigDecimal totalFee
            , String outRefundNo, String transactionId, SSLContext sslContext, String mchId) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        if (!StringUtils.isNotEmpty(appId)) {
            appId = iWeiXinAttributeItem.giveAppId();
        }
        final IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataBean(appId, totalFee, mchId);

        Map<String, Object> paraMap = new HashMap<String, Object>(16) {
            private static final long serialVersionUID = 6437941194831358070L;

            {
                put("mch_id", mchDataBean.getMchId());
                // 随机字符串，不长于32位
                put("nonce_str", createNonceStr());
                // 订单编号
                put("op_user_id", mchDataBean.getMchId());
                // 商户系统内部的退款单号，商户系统内部唯一，同一退款单号多次请求只退一笔
                put("out_refund_no", outRefundNo + RandomStringUtils.randomNumeric(4));
                //退款金额
                put("refund_fee", refundFee.multiply(BigDecimal.valueOf(100)).setScale(0
                        , RoundingMode.HALF_UP).toString());
                put("total_fee", totalFee.multiply(BigDecimal.valueOf(100)).setScale(0
                        , RoundingMode.HALF_UP).toString());
                //微信支付单号
                put("transaction_id", transactionId);
            }
        };
        paraMap.put("appid", appId);
        paraMap.put("sign", dataSignManager(paraMap, mchDataBean.getPayMchSecret()));
        log.debug("退款提交的参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveRefundPayOrderUrl(), String.class, requestHeaders -> {
            requestHeaders.setContentType(MediaType.APPLICATION_XML);
        }, () -> mapToXmlWith(paraMap), parameter -> {
        }, sslContext, reqeustValue -> {
            log.error("统一退款接口处理结果为：{}", reqeustValue);
            return strToXmlParse(reqeustValue);
        });
    }

    /**
     * 功能描述：根据条件获取支付数据
     *
     * @param appId      平台标识
     * @param totalFee   涉及的金额；
     * @param mchId      商户号
     * @return 商户对象
     * @date : 2022/11/17 0017 下午 4:53
     */
    @Override
    public IWeiXinAttributeItem.MchDataBean giveMchDataBean(String appId, BigDecimal totalFee, String mchId) throws Exception {
        IWeiXinAttributeItem.MchDataBean mchDataBean;
        if (StringUtils.isEmpty(mchId)) {
            mchDataBean = giveMchDataByAppIdToMap(appId, totalFee);
        } else {
            mchDataBean = giveMchDataByAppIdByRefundToMap(appId, mchId);
        }

        if (mchDataBean == null) {
            log.error("没有找到：{}；对应的支付数据；开始调用全量数据查询", mchId);
            mchDataBean = giveWeiXinPayMchDataBean(mchId);
            log.error("根据：{}；找到对应的支付账户数据为：{}", mchId, mchDataBean);
        }
        return mchDataBean;
    }

    protected static final String CHECK_NAME = "NO_CHECK";

    /**
     * 功能描述：提现
     *
     * @param appId        平台标识
     * @param openId       顾客OpenId
     * @param paymentTotal 付款金额
     * @param orderNo      付款编号
     * @param sslContext   证书配置
     * @throws Exception 处理异常
     * @date : 2022/9/24 0024 下午 3:41
     */
    @Override
    public Map<String, String> withdrawProcessing(String appId, String openId, BigDecimal paymentTotal, String orderNo
            , SSLContext sslContext) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        if (!StringUtils.isNotEmpty(appId)) {
            appId = iWeiXinAttributeItem.giveAppId();
        }
        IWeiXinAttributeItem.MchDataBean mchDataBean = giveWithdrawMchData(appId, paymentTotal);
        Map<String, Object> paraMap = new HashMap<String, Object>(16) {
            private static final long serialVersionUID = 6437941194831358070L;
            {
                // 微信分配的公众账号ID（企业号corpid即为此appId）
                put("mch_appid", iWeiXinAttributeItem.giveAppId());
                // 微信支付分配的商户号
                put("mchid", mchDataBean.getMchId());
                // 随机字符串，不长于32位
                put("nonce_str", createNonceStr());
                //提现单号
                put("partner_trade_no", orderNo);
                // 提现目标
                put("openid", openId);
                // 不校验用户名称
                put("check_name", CHECK_NAME);
                // 提现金额——分
                put("amount", paymentTotal.multiply(BigDecimal.valueOf(100)).setScale(0
                        , BigDecimal.ROUND_HALF_UP));
                put("desc", "提现");
                put("spbill_create_ip", "192.168.1.1");
            }
        };
        paraMap.put("sign", dataSignManager(paraMap, mchDataBean.getPayMchSecret()));
        log.debug("提现提交的参数结果为：{}", paraMap);
        //开始获取数据
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveWithdrawUrl(), String.class, requestHeaders -> {
            requestHeaders.setContentType(MediaType.APPLICATION_XML);
        }, () -> mapToXmlWith(paraMap), parameter -> {
        }, sslContext, reqeustValue -> {
            log.error("统一退款接口处理结果为：{}", reqeustValue);
            return strToXmlParse(reqeustValue);
        });
    }

    /**
     * 功能描述：统一退款处理-内置证书加载——小程序
     *
     * @param appId         平台标识
     * @param refundFee     退款金额
     * @param totalFee      订单支付总金额
     * @param outRefundNo   支付单号
     * @param transactionId 微信支付单号
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public Map<String, String> unifiedRefundProcessingBuiltInCertificateLoading(String appId, BigDecimal refundFee
            , BigDecimal totalFee, String outRefundNo, String transactionId) throws Exception {
        return unifiedRefundProcessingBuiltInCertificateLoading(appId, refundFee, totalFee, outRefundNo, transactionId, null);
    }

    /**
     * 功能描述：统一退款处理-内置证书加载——小程序
     *
     * @param appId         平台标识
     * @param refundFee     退款金额
     * @param totalFee      订单支付总金额
     * @param outRefundNo   支付单号
     * @param transactionId 微信支付单号
     * @param mchId         商户号
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public Map<String, String> unifiedRefundProcessingBuiltInCertificateLoading(String appId, BigDecimal refundFee
            , BigDecimal totalFee, String outRefundNo, String transactionId, String mchId) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);

        final IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataBean(iWeiXinAttributeItem.giveAppId(), totalFee, mchId);

        log.info("{}-refund：退款获取到的支付信息为{}", this.getClass(), mchDataBean.getMchId());
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream instream = new FileInputStream(new File(mchDataBean.getCertificateValue()
                + mchDataBean.getMchId() + ".p12"))) {
            keyStore.load(instream, mchDataBean.getMchId().toCharArray());
        }
        // Trust own CA and all self-signed certs
        return unifiedRefundProcessing(iWeiXinAttributeItem.giveAppId(), refundFee, totalFee, outRefundNo, transactionId
                , SSLContexts.custom().loadKeyMaterial(keyStore, mchDataBean.getMchId().toCharArray()).build(), mchId);
    }

    /**
     * 功能描述：统一提现处理-内置证书加载——小程序
     *
     * @param appId        平台标识
     * @param openId       顾客OpenId
     * @param paymentTotal 付款金额
     * @param orderNo      付款编号
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public Map<String, String> unifiedWithdrawProcessingBuiltInCertificateLoading(String appId, String openId
            , BigDecimal paymentTotal, String orderNo) throws Exception {
        final IWeiXinAttributeItem iWeiXinAttributeItem = giveWeiXinAttributeItem(appId);
        IWeiXinAttributeItem.MchDataBean mchDataBean = giveWithdrawMchData(iWeiXinAttributeItem.giveAppId(), paymentTotal);

        log.info("{}-withdraw：提现获取到的支付信息为{}", this.getClass(), mchDataBean.getMchId());
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream instream = new FileInputStream(new File(mchDataBean.getCertificateValue()
                + mchDataBean.getMchId() + ".p12"))) {
            keyStore.load(instream, mchDataBean.getMchId().toCharArray());
        }
        // Trust own CA and all self-signed certs
        return withdrawProcessing(iWeiXinAttributeItem.giveAppId(), openId, paymentTotal, orderNo
                , SSLContexts.custom().loadKeyMaterial(keyStore, mchDataBean.getMchId().toCharArray()).build());
    }

    /**
     * 功能描述：订单关闭处理
     *
     * @param appId     平台标识
     * @param orderNum  订单编号
     * @param mchId     支付ID
     * @param mchSecret 支付密钥
     * @param payTotal  订单金额
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public String orderClosureProcessing(String appId, String orderNum, String mchId
            , String mchSecret, BigDecimal payTotal) throws Exception {
        Map<String, Object> requestParameter = new HashMap<>(16);
        requestParameter.put("out_trade_no", orderNum);
        requestParameter.put("appid", appId);
        requestParameter.put("nonce_str", createNonceStr());

        IWeiXinAttributeItem.MchDataBean mchDataBean = giveMchDataBean(appId, payTotal, mchId);

        requestParameter.put("mch_id", mchDataBean.getMchId());
        requestParameter.put("sign", dataSignManager(requestParameter, mchDataBean.getPayMchSecret()));
        //开始关闭订单
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveRefundPayOrderUrl(), String.class
                , requestHeaders -> requestHeaders.setContentType(MediaType.APPLICATION_XML)
                , () -> mapToXmlWith(requestParameter), parameter -> {
                }, reqeustValue -> {
                    log.debug("统一退款接口处理结果为：{}", reqeustValue);
                    return reqeustValue;
                });
    }

    /**
     * 功能描述：订单关闭处理
     *
     * @param appId    平台标识
     * @param orderNum 订单编号
     * @param payTotal 订单金额
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public String orderClosureProcessing(String appId, String orderNum, BigDecimal payTotal) throws Exception {
        return orderClosureProcessing(appId, orderNum, null, null, payTotal);
    }

    /**
     * 功能描述：生成二维码
     *
     * @param appId        平台标识
     * @param parameterMap 参数
     * @throws Exception 处理异常
     * @author : 王雷
     * @date : 2022/7/19 0019 上午 11:12
     */
    @Override
    public <PM> JSONObject giveGenerateQrCode(String appId, PM parameterMap) throws Exception {
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveGenerateQrCodeUrl(), JSONObject.class
                , requestHeaders -> requestHeaders.setContentType(MediaType.APPLICATION_JSON)
                , () -> parameterMap, parameter -> httpAlternatelyParameterPutTokenManager(parameter, appId)
                , jsonObject -> {
                    log.debug("生成二维码接口处理结果为：{}", jsonObject);
                    return jsonObject;
                });
    }

    /**
     * 功能描述：推送模版消息
     *
     * @param appId       标识
     * @param sendMessage 推送的消息内容
     * @return 微信端返回结果
     * @date : 2023/2/1 0001 上午 10:09
     */
    @Override
    public JSONObject sendTemplateMessage(String appId, JSONObject sendMessage) throws Exception {
        return iWeiXinInteraction.httpByPost(iWeiXinAttributeStore.giveSendTemplateMessageUrl()
                , JSONObject.class, requestHeaders -> requestHeaders.setContentType(MediaType.APPLICATION_JSON)
                , sendMessage::toString, parameter -> httpAlternatelyParameterPutTokenManager(parameter, appId)
                , jsonObjectData -> {
                    log.debug("微信发送消息接口返回信息为：{}", jsonObjectData);
                    return jsonObjectData;
                });
    }

    /**
     * 功能描述：推送模版消息
     *
     * @param appId       标识
     * @param sendMessage 推送的消息内容
     * @return 微信端返回结果
     * @date : 2023/2/1 0001 上午 10:09
     */
    @Override
    public JSONObject sendTemplateMessage(String appId, WxTemplateMessage sendMessage) throws Exception {
        JSONObject sendJson = JSONObject.fromObject(sendMessage);
        sendJson.put("template_id", sendMessage.getTemplateId());
        sendJson.remove("templateId");
        return sendTemplateMessage(appId, sendJson);
    }
}
